/* * Fiscal Service Common Scripts */ 'use strict'; var i; // Object Assign Polyfill if ( typeof Object.assign != 'function' ) { Object.defineProperty( Object, 'assign', { value: function assign( target, varArgs ) { if ( target == null ) throw new TypeError( 'Cannot convert undefined or null to object' ); var to = Object( target ); for ( var index = 1; index < arguments.length; index ++ ) { var nextSource = arguments[ index ]; if ( nextSource != null ) for ( var nextKey in nextSource ) if ( Object.prototype.hasOwnProperty.call( nextSource, nextKey ) ) to[ nextKey ] = nextSource[ nextKey ]; } return to; }, writable: true, configurable: true } ); } // Object-fit Fallback if ( 'objectFit' in document.documentElement.style === false ) { var figures = document.querySelectorAll( 'figure.cover' ); for ( var i = 0; i < figures.length; i ++ ) { figures[ i ].style.backgroundImage = 'url(' + figures[ i ].children[ 0 ].src + ')'; figures[ i ].setAttribute( 'aria-label', figures[ i ].children[ 0 ].alt ); figures[ i ].className += ' compatible'; figures[ i ].innerHTML = ''; } } // Cookies Helper function Cookies( key, value, options ) { return arguments.length === 1 ? Cookies.get( key ) : Cookies.set( key, value, options ); } Cookies.get = function( key ) { var cookies = document.cookie.split( ';' ); for ( var i = 0; i < cookies.length; i ++ ) { var parts = cookies[ i ].match( /^\s*?(\S*?)=(.*?)$/ ); if ( parts && parts[ 1 ] == key ) return parts[ 2 ]; } return null; }; Cookies.set = function( key, value, days ) { var expires = ''; if ( days ) { var date = new Date(); date.setTime( Math.min( days * 8640000 + date.getTime(), 253402300799000 ) ); expires = '; expires=' + date.toUTCString(); } document.cookie = key + '=' + ( value || '' ) + expires + '; path=/'; }; Cookies.expire = function( key ) { Cookies.set( key, undefined ); }; // Focus outline hiding for mouse users function setupFocusRingHiding() { window.addEventListener( 'mousedown', function ( event ) { document.body.setAttribute( 'data-mouse-active', '' ); } ); window.addEventListener( 'keydown', function( event ) { document.body.removeAttribute( 'data-mouse-active' ); } ); } setupFocusRingHiding(); // Site search function setupSiteSearch() { window.usasearch_config = { siteHandle: 'fiscal' }; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '//search.usa.gov/javascripts/remote.loader.js'; document.getElementsByTagName('head')[0].appendChild(script); } setupSiteSearch(); // Expandables function Expandable( root ) { this.button = root; var icons = this.button.getAttribute( 'data-expandable-button' ).split( ' ' ); this.collapsedIcon = icons[ 0 ]; this.expandedIcon = icons[ 1 ]; this.region = document.getElementById( this.button.getAttribute( 'aria-controls' ) ); var wrapper = document.createElement( 'div' ); wrapper.className = 'wrapper'; while ( this.region.hasChildNodes() ) { wrapper.appendChild( this.region.removeChild( this.region.firstChild ) ); } this.region.appendChild( wrapper ); if ( window.TransitionEvent ) { this.region.addEventListener( 'transitionend', this.onTransitionEnd.bind( this ) ); } this.button.addEventListener( 'click', this.onToggle.bind( this ) ); this.button.addEventListener( 'keydown', this.onKeyDown.bind( this ) ); this.region.addEventListener( 'keydown', this.onKeyDown.bind( this ) ); } Expandable.prototype.expand = function() { this.region.style.height = window.TransitionEvent ? this.region.querySelector( '.wrapper' ).clientHeight + 'px' : 'auto'; this.button.setAttribute( 'aria-expanded', true ); this.button.className = this.button.className.replace( this.collapsedIcon, this.expandedIcon ); this.region.removeAttribute( 'hidden' ); this.region.removeAttribute( 'inert' ); }; Expandable.prototype.collapse = function() { this.button.setAttribute( 'aria-expanded', false ); this.button.className = this.button.className.replace( this.expandedIcon, this.collapsedIcon ); this.region.style.height = this.region.querySelector( '.wrapper' ).clientHeight + 'px'; this.region.clientHeight; // Force style recalculation this.region.setAttribute( 'hidden', '' ); this.region.setAttribute( 'inert', '' ); this.region.style.height = ''; }; Expandable.prototype.onTransitionEnd = function() { if ( this.button.getAttribute( 'aria-expanded' ) == 'true' ) { this.region.style.height = 'auto'; } } Expandable.prototype.onToggle = function() { if ( this.button.getAttribute( 'aria-expanded' ) == 'true' ) this.collapse(); else this.expand(); }; Expandable.prototype.onKeyDown = function( event ) { if ( event.keyCode === 27 && this.button.getAttribute( 'aria-expanded' ) == 'true' ) { event.stopPropagation(); this.collapse(); this.button.focus(); } }; var expandableButtons = document.querySelectorAll( '#main [data-expandable-button], #footer-site [data-expandable-button]' ); for ( i = 0; i < expandableButtons.length; i ++ ) new Expandable( expandableButtons[ i ] ); // Header Expandables var headerExpandables = []; var lastDirectInteraction; function HeaderExpandable( root ) { Expandable.call( this, root ); this.shouldTrapFocus = this.button.hasAttribute( 'data-trap-focus' ); if ( this.shouldTrapFocus ) { this.focusableElementsSelector = 'button:not([disabled]), input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), a, [tabindex]:not([disabled])'; var focusTrap = document.createElement( 'div' ); focusTrap.tabIndex = 0; this.focusTrapStart = focusTrap; this.focusTrapEnd = focusTrap.cloneNode( false ); this.focusTrapStart.addEventListener( 'focus', this.onFocus.bind( this ) ); this.focusTrapEnd.addEventListener( 'focus', this.onFocus.bind( this ) ); this.region.insertBefore( this.focusTrapStart, this.region.firstChild ); this.region.appendChild( this.focusTrapEnd ); } headerExpandables.push( this ); } HeaderExpandable.prototype = Object.create( Expandable.prototype ); HeaderExpandable.prototype.isChildOfHiddenElement = function( element ) { if ( !element.parentElement ) return false; if ( element.parentElement.getAttribute( 'hidden' ) === '' ) return true; return this.isChildOfHiddenElement( element.parentElement ); }; HeaderExpandable.prototype.focusFirstElement = function() { var wrapper = this.region.querySelector( '.wrapper' ); var allFocusableElements = wrapper.querySelectorAll( this.focusableElementsSelector ); if ( allFocusableElements.length < 1 ) { allFocusableElements.push( wrapper.firstElementChild ); allFocusableElements[ 0 ].tabIndex = -1; } var firstFocusableIndex = 0; while ( this.isChildOfHiddenElement( allFocusableElements[ firstFocusableIndex ] ) ) { if ( firstFocusableIndex == allFocusableElements.length - 1 ) break; firstFocusableIndex -= 1; } allFocusableElements[ firstFocusableIndex ].focus(); }; HeaderExpandable.prototype.focusLastElement = function() { var wrapper = this.region.querySelector( '.wrapper' ); var allFocusableElements = wrapper.querySelectorAll( this.focusableElementsSelector ); if ( allFocusableElements.length < 1 ) { allFocusableElements.push( wrapper.lastElementChild ); allFocusableElements[ 0 ].tabIndex = -1; } var lastFocusableIndex = allFocusableElements.length - 1; while ( this.isChildOfHiddenElement( allFocusableElements[ lastFocusableIndex ] ) ) { if ( lastFocusableIndex == 0 ) break; lastFocusableIndex -= 1; } allFocusableElements[ lastFocusableIndex ].focus(); }; HeaderExpandable.prototype.toggleAriaHiddenOnOthers = function( currentElement, shouldHide ) { if ( currentElement === document.body ) return; var siblings = currentElement.parentElement.children; for ( var i = 0; i < siblings.length; i++ ) { if ( siblings[i] === currentElement ) continue; shouldHide ? siblings[ i ].setAttribute( 'aria-hidden', 'true' ) : siblings[ i ].removeAttribute( 'aria-hidden' ); } this.toggleAriaHiddenOnOthers( currentElement.parentElement, shouldHide ); }; HeaderExpandable.prototype.expand = function() { this.collapseAll( true ); if ( this.shouldTrapFocus ) this.toggleAriaHiddenOnOthers( this.region, true ); Expandable.prototype.expand.call( this ); if ( this.shouldTrapFocus && !window.TransitionEvent ) this.focusFirstElement(); }; HeaderExpandable.prototype.collapse = function() { Expandable.prototype.collapse.call( this ); if ( this.shouldTrapFocus ) this.toggleAriaHiddenOnOthers( this.region, false ); if ( this.shouldTrapFocus && lastDirectInteraction == this ) this.button.focus(); }; HeaderExpandable.prototype.collapseAll = function( shouldExcludeAncestors ) { for ( var i = 0; i < headerExpandables.length; i ++ ) { if ( shouldExcludeAncestors && headerExpandables[ i ].region.contains( this.button ) ) { continue; } headerExpandables[ i ].collapse(); } }; HeaderExpandable.prototype.onTransitionEnd = function( event ) { Expandable.prototype.onTransitionEnd.call( this ); // Make sure that (1) we only assign focus when the region is expanded, and // (2) focus is only triggered once, since a `transitionend` event is // dispatched for each property being animated. if ( this.shouldTrapFocus && lastDirectInteraction == this && event.propertyName == 'visibility' && this.button.getAttribute( 'aria-expanded' ) == 'true' ) { this.focusFirstElement(); } }; HeaderExpandable.prototype.onToggle = function ( event ) { lastDirectInteraction = this; Expandable.prototype.onToggle.call( this, event ); }; HeaderExpandable.prototype.onKeyDown = function ( event ) { lastDirectInteraction = this; Expandable.prototype.onKeyDown.call( this, event ); }; HeaderExpandable.prototype.onFocus = function( event ) { if ( event.target == this.focusTrapEnd ) { this.focusFirstElement(); } else if ( event.target == this.focusTrapStart ) { this.focusLastElement(); } }; var headerExpandableButtons = document.querySelectorAll( '#header-site [data-expandable-button]' ); for ( var i = 0; i < headerExpandableButtons.length; i ++ ) new HeaderExpandable( headerExpandableButtons[ i ] ); // Tool Tips function ToolTip( root ) { var id = 'tooltip-' + +new Date(); this.container = document.createElement( 'div' ); this.container.className = 'tooltip'; root.parentNode.insertBefore( this.container, root ); this.container.appendChild( root ); this.term = root; this.term.className = ''; this.term.setAttribute( 'aria-expanded', false); this.term.setAttribute( 'aria-describedby', id ); this.tip = document.createElement( 'div' ); this.tip.setAttribute( 'role', 'tooltip' ); this.tip.setAttribute( 'hidden', '' ); this.tip.setAttribute( 'id', id ); this.tip.className = "small"; this.container.appendChild( this.tip ); this.tip.innerHTML = this.term.getAttribute( 'title' ); this.term.removeAttribute( 'title' ); this.term.addEventListener( 'click', this.onClick.bind( this ) ); this.term.addEventListener( 'focus', this.onFocus.bind( this ) ); this.term.addEventListener( 'blur', this.onBlur.bind( this ) ); } ToolTip.prototype.onClick = function() { this.term.focus(); }; ToolTip.prototype.onFocus = function() { this.term.setAttribute( 'aria-expanded', true ); this.tip.removeAttribute( 'hidden' ); }; ToolTip.prototype.onBlur = function() { this.term.setAttribute( 'aria-expanded', false ); this.tip.setAttribute( 'hidden', '' ); }; var toolTips = document.querySelectorAll( 'button.tooltip' ); for ( i = 0; i < toolTips.length; i ++ ) new ToolTip( toolTips[ i ] ); // Alert Banners function AlertBanner( root ) { this.container = root; if ( this.container.id === '' ) throw new Error( ' requires a unique "id" attribute.' ); if ( Cookies( this.container.id ) ) this.dismiss(); this.button = this.container.querySelector( 'button' ); this.button.addEventListener( 'click', this.onClick.bind( this ) ); } AlertBanner.prototype.setCookie = function() { Cookies.set( this.container.id, 'dismissed', Infinity ); }; AlertBanner.prototype.dismiss = function() { this.container.setAttribute( 'hidden', '' ); this.container.setAttribute( 'inert', '' ); }; AlertBanner.prototype.onClick = function() { this.setCookie(); this.dismiss(); }; var alertBanners = document.querySelectorAll( 'alert-banner' ); for ( i = 0; i < alertBanners.length; i ++ ) { try { new AlertBanner( alertBanners[ i ] ); } catch ( error ) { console.error( error ); } }